/*
  This is unclassified Government software.

  The SCPS File Protocol (SCPS-FP) software was developed under
  contract to the Jet Propulsion Laboratory, an operating division of
  the California Institute of Technology and is available for use by
  the public without need of a licence.

  DISCLAIMER:

  THE SCPS-FP SOFTWARE AND RELATED MATERIALS ARE PROVIDED "AS-IS"
  WITHOUT WARRANTY OR INDEMNITY OF ANY KIND INCLUDING ANY WARRANTIES
  OF USE, PEROFMRNACE, OR MERCHANTABILITY OR FITNESS FOR A PRTICULAR
  USE OR PURPOSE (as set forth in UCC section 2312-2313) OR FOR ANY
  PURPOSE WHATSOEVER.

  USER BEARS ALL RISK RELATING TO USE, QUALITY, AND PERFORMANCE OF THE
  SOFTWARE.

  The Jet Propulsion Laboratory, the California Institute of
  Technology, and the United States government retain a paid-up
  royalty free world wide license in this product.

  SAIC Disclaimer:
    (1) SAIC assumes no legal responsibility for the source code and
        its subsequent use.
    (2) No warranty or representation is expressed or implied.
    (3) Portions (e.g. Washington University FTP Replacement Daemon)
        are copyright (c) Regents of the University of California.
	All rights reserved.  Restrictions included in said copyright
	are also applicable to this release.

*/

/********************************************************************/
/*  Created by      :                                               */
/*                     Steven R. Sides                              */
/*                     steven.r.sides@cpmx.saic.com                 */
/*                     Thursday, November 7, 1996 2:17 pm           */
/*                                                                  */
/*  Modified by     :                                               */
/*                                                                  */
/********************************************************************/
/********************************************************************/
/* Module:             edit.c                                       */
/*                                                                  */
/* Description:                                                     */
/*    Applies the record update "script" to the input file, writing
 *    the result to the output file.
 * $Id: edit.c,v 1.10 2007/04/19 15:09:36 feighery Exp $
 * $Header: /home/cvsroot/SCPS_RI/FP/edit.c,v 1.10 2007/04/19 15:09:36 feighery Exp $
 * 
 *    Change History:
 * $Log: edit.c,v $
 * Revision 1.10  2007/04/19 15:09:36  feighery
 * This version makes the gateway code (and only the gateway code) safe for
 * 64 bit architectures.  Before we were very sloppy and use a long and int
 * interchangeable.  As part of this change, it was required to make the
 * gateway code single threaded;  therefore gateway_single_thread=yes is the
 * default.  -- PDF
 *
 * Revision 1.9  1999/11/22 16:14:33  scps
 * Removed disclaimer comment blocks from revision logs.
 *
 * Revision 1.8  1999/11/22 15:52:43  scps
 * Changed FP discaimers 
 *
 * Revision 1.7  1999/03/23 20:24:35  scps
 * Merged reference implementation with gateway-1-1-6-k branch.
 *
 * Revision 1.6.2.2  1999/01/22 15:02:32  scps
 * There was a problem with the FP in CVS I had to perform a update and a new
 * commit. -- PDF
 *
 * Revision 1.6.2.1  1998/12/29 14:27:30  scps
 * Monolithic update to include gateway code.
 *
 * Revision 1.6  1998/12/01 16:44:37  scps
 * Update to version 1.1.6 --ks
 *
 * Revision 1.4  1997/09/18 17:57:16  steven
 * Red-3 except files of CCSDS packets.
 *
 * Revision 1.3  1997/08/21 16:33:26  steven
 * Changed copyright notice.
 * 
 * Revision 1.2  1997/06/16 14:09:30  steven
 * Added sizes MEDIUM and LARGE.
 * 
 * Revision 1.1  1997/02/28 21:25:57  steven
 * Initial revision
 *                                                                  */
/********************************************************************/

static char rcsid[] = "$Id: edit.c,v 1.10 2007/04/19 15:09:36 feighery Exp $";

#include <stdio.h>
#include <sys/types.h>
#ifdef MSVC
#include <winsock.h>
#else
#include <unistd.h>
#include <netinet/in.h>		/* for ntohl and htonl stuff */
#endif
#include "edit.h"
#include "fileio.h"


/* edit - Modifies the original file based on the delta file.
 *        Writes output to nfile.  Delta file is generated by
 *        you.  
 *
 *     d<file-offset><length>            // delete
 *     a<file-offset><length><data>      // add after
 *     i<file-offset><length><data>      // insert before
 *     w<file-offset><length><data>      // overwrite.
 *
 * Returns 0 if all went OK
 *         1 if invalid offsets	or commands were specified in the delta file. 
 *         2 if unable to open either original file, delta file,
 *           or new file.
 */
int
edit (char *ofile,
      char *nfile,
      char *dfile)
{
  FILE *of;
  FILE *nf;
  FILE *df;
  int editres = 0;
  u_long ofilesize;
  u_long ofilepos;
  u_long offset;
  struct change_cmd chcmd;
  char ch;


  of = Lfopen (ofile, "r");
  if (of == NULL)
    return (2);
  df = Lfopen (dfile, "r");
  if (df == NULL)
    {
      Lfclose (of);
      return (2);
    }				/* df */
  nf = Lfopen (nfile, "w");
  if (nf == NULL)
    {
      Lfclose (of);
      Lfclose (df);
      return (2);
    }				/* nf */
  fseek (of, 0, SEEK_END);
  ofilesize = ftell (of);
  fseek (of, 0, SEEK_SET);
  ofilepos = 0;
  while (get_ch_rec (&chcmd, df))
    {
      offset = chcmd.foffset;
      /* The character at ofilepos has not yet been read */
      /* advance to the indicated position */
      for (; ofilepos != offset; ofilepos++)
	{
	  if (fread (&ch, 1, 1, of) != 1)
	    {
	      editres = 1;
	      goto editdone;
	    }
	  if (fwrite (&ch, 1, 1, nf) != 1)
	    {
	      editres = 1;
	      goto editdone;
	    }
	}			/* advance */
      switch (chcmd.ch)
	{
	case 'd':
	  chcmd.foffset += chcmd.len;
	  for (; ofilepos != chcmd.foffset; ofilepos++)
	    {
	      if (fread (&ch, 1, 1, of) != 1)
		{
		  editres = 1;
		  goto editdone;
		}
	    }
	  break;

	case 'a':
	  /* I'm going to insert stuff
	   * after this character */
	  if (fread (&ch, 1, 1, of) != 1)
	    {
	      editres = 1;
	      goto editdone;
	    }
	  if (fwrite (&ch, 1, 1, nf) != 1)
	    {
	      editres = 1;
	      goto editdone;
	    }
	  ofilepos++;
	  while (chcmd.len--)
	    {
	      if (fread (&ch, 1, 1, df) != 1)
		{
		  /* couldn't read the character
		   * to insert */
		  editres = 1;
		  goto editdone;
		}
	      if (fwrite (&ch, 1, 1, nf) != 1)
		{
		  editres = 1;
		  goto editdone;
		}
	    }			/* while */
	  break;

	case 'i':
	  {
	    while (chcmd.len--)
	      {
		if (fread (&ch, 1, 1, df) != 1)
		  {
		    /* couldn't read the character
		     * to insert */
		    editres = 1;
		    goto editdone;
		  }
		if (fwrite (&ch, 1, 1, nf) != 1)
		  {
		    editres = 1;
		    goto editdone;
		  }
	      }			/* while */
	  }
	  break;

	case 'w':
	  chcmd.foffset += chcmd.len;
	  for (; ofilepos != chcmd.foffset; ofilepos++)
	    {
	      /* read this from the original file
	       * in order to throw it away */
	      if (fread (&ch, 1, 1, of) != 1)
		{
		  editres = 1;
		  goto editdone;
		}		/* read original file */
	      /* read a character from the delta file */
	      if (fread (&ch, 1, 1, df) != 1)
		{
		  editres = 1;
		  goto editdone;
		}
	      /* write it to the new file */
	      if (fwrite (&ch, 1, 1, nf) != 1)
		{
		  editres = 1;
		  goto editdone;
		}
	    }
	  break;

	default:
	  editres = 1;
	  goto editdone;
	}			/* switch */
    }				/* for all change records */

  while (fread (&ch, 1, 1, of))
    {
      fwrite (&ch, 1, 1, nf);
    }				/* while */

editdone:
  Lfclose (of);
  Lfclose (df);
  Lfclose (nf);
  return (editres);
}				/* edit */


/* get_ch_rec - get a change record 
 */

int
get_ch_rec (struct change_cmd *chcmdp, FILE * rf)
{
  int rdres = 0;
  int32_t ltemp;
  short stemp;


  rdres = fread (&(chcmdp->ch), 1, 1, rf);
  rdres += fread (&(chcmdp->foffset), 1, 4, rf);
  rdres += fread (&(chcmdp->len), 1, 2, rf);
  ltemp = ntohl (chcmdp->foffset);
  stemp = ntohs (chcmdp->len);
  chcmdp->foffset = ltemp;
  chcmdp->len = stemp;
  return (rdres == 7);
}				/* get_ch_rec */
